home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / comm / wnos5src.zip / TCPHDR.C < prev    next >
Text File  |  1993-08-09  |  4KB  |  153 lines

  1. /* TCP header conversion routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "tcp.h"
  7. #include "ip.h"
  8. #include "internet.h"
  9.  
  10. /* Convert TCP header in host format into mbuf ready for transmission,
  11.  * link in data (if any). If ph != NULL, compute checksum, otherwise
  12.  * take checksum from tcph->checksum
  13.  */
  14. struct mbuf *
  15. htontcp(struct tcp *tcph,struct mbuf *data,struct pseudo_header *ph)
  16. {
  17.     int16 hdrlen = TCPLEN;
  18.     struct mbuf *bp;
  19.     char *cp;
  20.  
  21.     if(tcph->optlen > 0 && tcph->optlen <= TCP_MAXOPT){
  22.         hdrlen += tcph->optlen;
  23.     } else if(tcph->mss != 0){
  24.         hdrlen += MSS_LENGTH;
  25.     }
  26.     bp = pushdown(data,hdrlen);
  27.     cp = bp->data;
  28.     cp = put16(cp,tcph->source);
  29.     cp = put16(cp,tcph->dest);
  30.     cp = put32(cp,tcph->seq);
  31.     cp = put32(cp,tcph->ack);
  32.     *cp++ = hdrlen << 2;    /* Offset field */
  33.     *cp = 0;
  34.     if(tcph->flags.congest)
  35.         *cp |= 64;
  36.     if(tcph->flags.urg)
  37.         *cp |= 32;
  38.     if(tcph->flags.ack)
  39.         *cp |= 16;
  40.     if(tcph->flags.psh)
  41.         *cp |= 8;
  42.     if(tcph->flags.rst)
  43.         *cp |= 4;
  44.     if(tcph->flags.syn)
  45.         *cp |= 2;
  46.     if(tcph->flags.fin)
  47.         *cp |= 1;
  48.     cp++;
  49.     cp = put16(cp,tcph->wnd);
  50.  
  51.     if(ph == NULLHEADER){
  52.         /* Use user-supplied checksum */
  53.         cp = put16(cp,tcph->checksum);
  54.     } else {
  55.         /* Zero out checksum field for later recalculation */
  56.         *cp++ = 0;
  57.         *cp++ = 0;
  58.     }
  59.     cp = put16(cp,tcph->up);
  60.  
  61.     /* Write options, if any */
  62.     if(hdrlen > TCPLEN){
  63.         if(tcph->mss != 0){
  64.             *cp++ = MSS_KIND;
  65.             *cp++ = MSS_LENGTH;
  66.             cp = put16(cp,tcph->mss);
  67.         } else {
  68.             memcpy(cp,tcph->options,tcph->optlen);
  69.         }
  70.     }
  71.     /* Recompute checksum, if requested */
  72.     if(ph != NULLHEADER)
  73.         put16(&bp->data[16],cksum(ph,bp,ph->length));
  74.  
  75.     return bp;
  76. }
  77.  
  78. /* Pull TCP header off mbuf */
  79. int
  80. ntohtcp(struct tcp *tcph,struct mbuf **bpp)
  81. {
  82.     char hdrbuf[TCPLEN], *cp;
  83.     int flags, hdrlen, optlen, kind, i = pullup(bpp,hdrbuf,TCPLEN);
  84.  
  85.     /* Note that the results will be garbage if the header is too short.
  86.      * We don't check for this because returned ICMP messages will be
  87.      * truncated, and we at least want to get the port numbers.
  88.      */
  89.     tcph->source = get16(&hdrbuf[0]);
  90.     tcph->dest = get16(&hdrbuf[2]);
  91.     tcph->seq = get32(&hdrbuf[4]);
  92.     tcph->ack = get32(&hdrbuf[8]);
  93.     hdrlen = (hdrbuf[12] & 0xf0) >> 2;
  94.     flags = hdrbuf[13];
  95.     tcph->flags.congest = flags & 64;
  96.     tcph->flags.urg = flags & 32;
  97.     tcph->flags.ack = flags & 16;
  98.     tcph->flags.psh = flags & 8;
  99.     tcph->flags.rst = flags & 4;
  100.     tcph->flags.syn = flags & 2;
  101.     tcph->flags.fin = flags & 1;
  102.     tcph->wnd = get16(&hdrbuf[14]);
  103.     tcph->checksum = get16(&hdrbuf[16]);
  104.     tcph->up = get16(&hdrbuf[18]);
  105.     tcph->mss = 0;
  106.     tcph->optlen = hdrlen - TCPLEN;
  107.  
  108.     /* Check for option field. Only space for one is allowed, but
  109.      * since there's only one TCP option (MSS) this isn't a problem
  110.      */
  111.     if(i < TCPLEN || hdrlen < TCPLEN)
  112.         return -1;    /* Header smaller than legal minimum */
  113.  
  114.     if(tcph->optlen == 0)
  115.         return (int)hdrlen;    /* No options, all done */
  116.  
  117.     if(tcph->optlen > len_p(*bpp))
  118.         /* Remainder too short for options length specified */
  119.         return -1;
  120.  
  121.     pullup(bpp,tcph->options,tcph->optlen);    /* "Can't fail" */
  122.     /* Process options */
  123.     for(cp = tcph->options, i = tcph->optlen; i > 0; ) {
  124.         kind = *cp++;
  125.         /* Process single-byte options */
  126.         switch(kind){
  127.         case EOL_KIND:
  128.         case NOOP_KIND:
  129.             i--;
  130.             cp++;
  131.             if(kind == NOOP_KIND)
  132.                 /* Go look for next option */
  133.                 continue;
  134.             return hdrlen;        /* End of options list */
  135.         }
  136.         /* All other options have a length field */
  137.         optlen = uchar(*cp++);
  138.  
  139.         /* Process valid multi-byte options */
  140.         switch(kind){
  141.         case MSS_KIND:
  142.             if(optlen == MSS_LENGTH){
  143.                 tcph->mss = get16(cp);
  144.             }
  145.             break;
  146.         }
  147.         optlen = max(2,optlen);    /* Enforce legal minimum */
  148.         i -= optlen;
  149.         cp += optlen - 2;
  150.     }
  151.     return hdrlen;
  152. }
  153.